#include <iostream>
#include <sys/epoll.h>
#include <unistd.h>
#include <string>
#include <cstdlib>
#include "Sock.hpp"
#define SIZE 128
#define NUM 64
static void Usage(const std::string &proc)
{
    std::cout << "Usage: " << proc << " port" << std::endl;
}
int main(int argc, char *argv[])
{

    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }
    uint16_t port = (uint16_t)atoi(argv[1]);
    int listen_sock = Sock::Socket();
    Sock::Bind(listen_sock, port);
    Sock::Listen(listen_sock);

    int epfd = epoll_create(SIZE);
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = listen_sock;
    epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sock, &ev);

    struct epoll_event revs[NUM];
    while (true)
    {
        int timeout = 1000;
        int n = epoll_wait(epfd, revs, NUM, timeout);
        switch (n)
        {
        case -1:
            std::cerr << "select error" << std::endl;
            break;
        case 0:
            std::cout << "select timeout" << std::endl;
            break;
        default:
            std::cout << "有fd对应事件就绪了" << std::endl;
            for (int i = 0; i < n; i++)
            {
                int sock = revs[i].data.fd; //暂时方案
                std::cout << "文件描述符: " << sock << " 上面有事件就绪啦" << std::endl;
                if (revs[i].events & EPOLLIN)
                {
                    std::cout << "文件描述符: " << sock << " 读事件就绪" << std::endl;
                    if (sock == listen_sock)
                    {
                        std::cout << "文件描述符: " << sock << " 链接数据就绪" << std::endl;
                        int fd = Sock::Accept(listen_sock);
                        if (fd > 0)
                        {
                            struct epoll_event _ev;
                            _ev.events = EPOLLIN;
                            _ev.data.fd = fd;
                            epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &_ev);
                            std::cout << "已经将" << fd << " 托管给epoll啦" << std::endl;
                        }
                        else
                        {
                            // do nothing
                        }
                    }
                    else
                    {
                        // 正常的读取处理
                        std::cout << "文件描述符: " << sock << "正常数据就绪" << std::endl;
                        char buffer[1024];
                        ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0);
                        if (s > 0)
                        {
                            buffer[s] = 0;
                            std::cout << "client [" << sock << "]# " << buffer << std::endl;

                            //将我们的关心时间更改成为EPOLLOUT
                            // struct epoll_event _ev;
                            // _ev.events = EPOLLOUT;
                            // _ev.data.fd = sock;
                            // epoll_ctl(epfd, EPOLL_CTL_MOD, sock, &_ev);
                        }
                        else if (s == 0)
                        {
                            //对端关闭链接
                            std::cout << "client quit " << sock << std::endl;
                            close(sock);
                            epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);
                            std::cout << "sock: " << sock << "delete from epoll success" << std::endl;
                        }
                        else
                        {
                            //读取失败
                            std::cout << "recv error" << std::endl;
                            close(sock);
                            epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);
                            std::cout << "sock: " << sock << "delete from epoll success" << std::endl;
                        }
                    }
                }
                else if (revs[i].events & EPOLLOUT)
                {
                    //处写事件就绪
                }
                else
                {
                    // other
                }
            }
            break;
        }
    }

    close(epfd);
    close(listen_sock);
    return 0;
}